home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Games / Tetris / Source / RCS / Piece.m,v < prev    next >
Encoding:
Text File  |  1975-04-26  |  24.6 KB  |  1,196 lines

  1. head     1.8;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ;
  6. comment  @@;
  7.  
  8.  
  9. 1.8
  10. date     92.03.01.10.26.53;  author melling;  state Exp;
  11. branches ;
  12. next     1.7;
  13.  
  14. 1.7
  15. date     92.03.01.05.07.36;  author melling;  state Exp;
  16. branches ;
  17. next     1.6;
  18.  
  19. 1.6
  20. date     92.02.29.20.35.44;  author melling;  state Exp;
  21. branches ;
  22. next     1.5;
  23.  
  24. 1.5
  25. date     92.02.28.05.18.53;  author melling;  state Exp;
  26. branches ;
  27. next     1.4;
  28.  
  29. 1.4
  30. date     91.12.19.10.12.37;  author melling;  state Exp;
  31. branches ;
  32. next     1.3;
  33.  
  34. 1.3
  35. date     91.12.16.17.22.03;  author melling;  state Exp;
  36. branches ;
  37. next     1.2;
  38.  
  39. 1.2
  40. date     91.12.07.07.49.02;  author melling;  state Exp;
  41. branches ;
  42. next     1.1;
  43.  
  44. 1.1
  45. date     91.12.07.03.36.54;  author melling;  state Exp;
  46. branches ;
  47. next     ;
  48.  
  49.  
  50. desc
  51. @Tetris 1.1
  52. @
  53.  
  54.  
  55. 1.8
  56. log
  57. @Release 1.3
  58. @
  59. text
  60. @#import <appkit/Application.h>
  61. #import <appkit/NXImage.h>
  62. #import <appkit/Window.h>
  63. #import <dpsclient/wraps.h>
  64. #import "Piece.h"
  65. #import "TetMatrix.h"
  66.  
  67. // The number of pixels to move a block at once when it is dropped.
  68. //static const float ANM_DELTA = 12.0;
  69. static const float ANM_DELTA = 28.0;
  70.  
  71. extern long random();
  72. extern void srandom(int seed);
  73. extern int getpid();
  74.  
  75. @@implementation Piece
  76.  
  77. #define PIECE_NULL    (unsigned char *)0;
  78. #define SHAPE_NULL    (struct shape *)0;
  79. const int NUM_ROTATIONS = 4;
  80. const int NUM_SHAPES=7;
  81.  
  82. #define XMIN_BOUNDS(BOUNDS)    ((BOUNDS & 0xc0) >> 6)
  83. #define YMIN_BOUNDS(BOUNDS)    ((BOUNDS & 0x30) >> 4)
  84. #define XMAX_BOUNDS(BOUNDS)    ((BOUNDS & 0xc) >> 2)
  85. #define YMAX_BOUNDS(BOUNDS)    (BOUNDS & 0x3)
  86.  
  87. - (void) setShapes
  88. {
  89.     /*  ** 1st shape ** */
  90.  
  91.     shapes[0].table[0][0] = 0x0;
  92.     shapes[0].table[0][1] = 0xf;    // ####
  93.     shapes[0].table[0][2] = 0x0;
  94.     shapes[0].table[0][3] = 0x0;     //  x,y  x1,y1
  95.     shapes[0].bounds[0] = 0x2e;        // (0, 2, 3, 2) 3*4 + 2 = 14 = 0xe 
  96.     shapes[0].points[0] = 10;            // This piece is worth 10 points
  97.  
  98.     shapes[0].table[1][0] = 0x4;    //  #
  99.     shapes[0].table[1][1] = 0x4;    //  #
  100.     shapes[0].table[1][2] = 0x4;    //  #
  101.     shapes[0].table[1][3] = 0x4;    //  #
  102.     shapes[0].bounds[1] = 0x47;        // (1, 0, 1, 3)
  103.     shapes[0].points[1] = 16;
  104.  
  105.     shapes[0].table[2][0] = 0x0;
  106.     shapes[0].table[2][1] = 0xf;    // ####
  107.     shapes[0].table[2][2] = 0x0;
  108.     shapes[0].table[2][3] = 0x0;
  109.     shapes[0].bounds[2] = 0x2e;        // (0, 2, 3, 2)
  110.     shapes[0].points[2] = 10;
  111.  
  112.     shapes[0].table[3][0] = 0x4;    //  #
  113.     shapes[0].table[3][1] = 0x4;    //  #
  114.     shapes[0].table[3][2] = 0x4;    //  #
  115.     shapes[0].table[3][3] = 0x4;    //  #
  116.     shapes[0].bounds[3] = 0x47;        // (1, 0, 1, 3)
  117.     shapes[0].points[3] = 16;
  118.  
  119.  
  120.     /* **  2nd shape ** */
  121.  
  122.     shapes[1].table[0][0] = 0xc;    // ##
  123.     shapes[1].table[0][1] = 0xc;    // ##
  124.     shapes[1].table[0][2] = 0x0;
  125.     shapes[1].table[0][3] = 0x0;
  126.     shapes[1].bounds[0] = 0x27;        // (0, 2, 1, 3)
  127.     shapes[1].points[0] = 12;
  128.  
  129.     shapes[1].table[1][0] = 0xc;    // ##
  130.     shapes[1].table[1][1] = 0xc;    // ##
  131.     shapes[1].table[1][2] = 0x0;
  132.     shapes[1].table[1][3] = 0x0;
  133.     shapes[1].bounds[1] = 0x27;        // (0, 2, 1, 3)
  134.     shapes[1].points[1] = 12;
  135.  
  136.     shapes[1].table[2][0] = 0xc;    // ##
  137.     shapes[1].table[2][1] = 0xc;    // ##
  138.     shapes[1].table[2][2] = 0x0;
  139.     shapes[1].table[2][3] = 0x0;
  140.     shapes[1].bounds[2] = 0x27;        // (0, 2, 1, 3)
  141.     shapes[1].points[2] = 12;
  142.  
  143.     shapes[1].table[3][0] = 0xc;    // ##
  144.     shapes[1].table[3][1] = 0xc;    // ##
  145.     shapes[1].table[3][2] = 0x0;
  146.     shapes[1].table[3][3] = 0x0;
  147.     shapes[1].bounds[3] = 0x27;        // (0, 2, 1, 3)
  148.     shapes[1].points[3] = 12;
  149.  
  150.  
  151.     /* ** 3rd shape ** */
  152.  
  153.     shapes[2].table[0][0] = 0x4;    //  #
  154.     shapes[2].table[0][1] = 0xe;    // ###
  155.     shapes[2].table[0][2] = 0x0;
  156.     shapes[2].table[0][3] = 0x0;
  157.     shapes[2].bounds[0] = 0x2b;        // (0, 2, 2, 3)
  158.     shapes[2].points[0] = 10;
  159.  
  160.     shapes[2].table[1][0] = 0x4;    //  #
  161.     shapes[2].table[1][1] = 0x6;    //  ##
  162.     shapes[2].table[1][2] = 0x4;    //  #
  163.     shapes[2].table[1][3] = 0x0;
  164.     shapes[2].bounds[1] = 0x5b;        // (1, 1, 2, 3)
  165.     shapes[2].points[1] = 10;
  166.  
  167.     shapes[2].table[2][0] = 0x0;
  168.     shapes[2].table[2][1] = 0xe;    // ###
  169.     shapes[2].table[2][2] = 0x4;    //  #
  170.     shapes[2].table[2][3] = 0x0;
  171.     shapes[2].bounds[2] = 0x1a;        // (0, 1, 2, 2)
  172.     shapes[2].points[2] = 12;
  173.  
  174.     shapes[2].table[3][0] = 0x4;    //  #
  175.     shapes[2].table[3][1] = 0xc;    // ##
  176.     shapes[2].table[3][2] = 0x4;    //  #
  177.     shapes[2].table[3][3] = 0x0;
  178.     shapes[2].bounds[3] = 0x17;        // (0, 1, 1, 3)
  179.     shapes[2].points[3] = 10;
  180.  
  181.  
  182.     // 4th shape
  183.  
  184.     shapes[3].table[0][0] = 0xc;    // ##
  185.     shapes[3].table[0][1] = 0x6;    //  ##
  186.     shapes[3].table[0][2] = 0x0;
  187.     shapes[3].table[0][3] = 0x0;
  188.     shapes[3].bounds[0] = 0x2b;        // (0, 2, 2, 3)
  189.     shapes[3].points[0] = 12;
  190.  
  191.     shapes[3].table[1][0] = 0x4;    //  #
  192.     shapes[3].table[1][1] = 0xc;    // ##
  193.     shapes[3].table[1][2] = 0x8;    // #
  194.     shapes[3].table[1][3] = 0x0;
  195.     shapes[3].bounds[1] = 0x17;        // (0, 1, 1, 3)
  196.     shapes[3].points[1] = 14;
  197.  
  198.     shapes[3].table[2][0] = 0xc;    // ##
  199.     shapes[3].table[2][1] = 0x6;    //  ##
  200.     shapes[3].table[2][2] = 0x0;
  201.     shapes[3].table[2][3] = 0x0;
  202.     shapes[3].bounds[2] = 0x2b;        // (0, 2, 2, 3)
  203.     shapes[3].points[2] = 12;
  204.  
  205.     shapes[3].table[3][0] = 0x4;    //  #
  206.     shapes[3].table[3][1] = 0xc;    // ##
  207.     shapes[3].table[3][2] = 0x8;    // #
  208.     shapes[3].table[3][3] = 0x0;
  209.     shapes[3].bounds[3] = 0x17;        // (0, 1, 1, 3)
  210.     shapes[3].points[3] = 14;
  211.  
  212.  
  213.     // 5th shape
  214.  
  215.     shapes[4].table[0][0] = 0x6;    //  ##
  216.     shapes[4].table[0][1] = 0xc;    // ##
  217.     shapes[4].table[0][2] = 0x0;
  218.     shapes[4].table[0][3] = 0x0;
  219.     shapes[4].bounds[0] = 0x2b;        // (0, 2, 2, 3)
  220.     shapes[4].points[0] = 12;
  221.     
  222.     shapes[4].table[1][0] = 0x8;    // #
  223.     shapes[4].table[1][1] = 0xc;    // ##
  224.     shapes[4].table[1][2] = 0x4;    //  #
  225.     shapes[4].table[1][3] = 0x0;
  226.     shapes[4].bounds[1] = 0x17;        // (0, 1, 1, 3)
  227.     shapes[4].points[1] = 14;
  228.     
  229.     shapes[4].table[2][0] = 0x6;    //  ##
  230.     shapes[4].table[2][1] = 0xc;    // ##
  231.     shapes[4].table[2][2] = 0x0;
  232.     shapes[4].table[2][3] = 0x0;
  233.     shapes[4].bounds[2] = 0x2b;        // (0, 2, 2, 3)
  234.     shapes[4].points[2] = 12;
  235.     
  236.     shapes[4].table[3][0] = 0x8;    // #
  237.     shapes[4].table[3][1] = 0xc;    // ##
  238.     shapes[4].table[3][2] = 0x4;    //  #
  239.     shapes[4].table[3][3] = 0x0;
  240.     shapes[4].bounds[3] = 0x17;        // (0, 1, 1, 3)
  241.     shapes[4].points[3] = 14;
  242.  
  243.  
  244.     // 6th shape
  245.  
  246.     shapes[5].table[0][0] = 0x2;    //   #
  247.     shapes[5].table[0][1] = 0xe;    // ###
  248.     shapes[5].table[0][2] = 0x0;
  249.     shapes[5].table[0][3] = 0x0;
  250.     shapes[5].bounds[0] = 0x2b;        // (0, 2, 2, 3)
  251.     shapes[5].points[0] = 6;
  252.  
  253.     shapes[5].table[1][0] = 0x8;    // #
  254.     shapes[5].table[1][1] = 0x8;    // #
  255.     shapes[5].table[1][2] = 0xc;    // ##
  256.     shapes[5].table[1][3] = 0x0;
  257.     shapes[5].bounds[1] = 0x17;        // (0, 1, 1, 3)
  258.     shapes[5].points[1] = 7;
  259.  
  260.     shapes[5].table[2][0] = 0xe;    // ###
  261.     shapes[5].table[2][1] = 0x8;    // #
  262.     shapes[5].table[2][2] = 0x0;
  263.     shapes[5].table[2][3] = 0x0;
  264.     shapes[5].bounds[2] = 0x2b;        // (0, 2, 2, 3)
  265.     shapes[5].points[2] = 6;
  266.  
  267.     shapes[5].table[3][0] = 0xc;    // ##
  268.     shapes[5].table[3][1] = 0x4;    //  #
  269.     shapes[5].table[3][2] = 0x4;    //  #
  270.     shapes[5].table[3][3] = 0x0;
  271.     shapes[5].bounds[3] = 0x17;        // (0, 1, 1, 3)
  272.     shapes[5].points[3] = 7;
  273.  
  274.  
  275.     // 7th shape
  276.  
  277.     shapes[6].table[0][0] = 0xe;    // ###
  278.     shapes[6].table[0][1] = 0x2;    //   #
  279.     shapes[6].table[0][2] = 0x0;
  280.     shapes[6].table[0][3] = 0x0;
  281.     shapes[6].bounds[0] = 0x2b;        // (0, 2, 2, 3)
  282.     shapes[6].points[0] = 6;
  283.  
  284.     shapes[6].table[1][0] = 0x4;    //  #
  285.     shapes[6].table[1][1] = 0x4;    //  #
  286.     shapes[6].table[1][2] = 0xc;    // ##
  287.     shapes[6].table[1][3] = 0x0;
  288.     shapes[6].bounds[1] = 0x17;        // (0, 1, 1, 3)
  289.     shapes[6].points[1] = 7;
  290.  
  291.     shapes[6].table[2][0] = 0x8;    // #
  292.     shapes[6].table[2][1] = 0xe;    // ###
  293.     shapes[6].table[2][2] = 0x0;
  294.     shapes[6].table[2][3] = 0x0;
  295.     shapes[6].bounds[2] = 0x2b;        // (0, 2, 2, 3)
  296.     shapes[6].points[2] = 6;
  297.  
  298.     shapes[6].table[3][0] = 0xc;    // ##
  299.     shapes[6].table[3][1] = 0x8;    // #
  300.     shapes[6].table[3][2] = 0x8;    // #
  301.     shapes[6].table[3][3] = 0x0;
  302.     shapes[6].bounds[3] = 0x17;        // (0, 1, 1, 3)
  303.     shapes[6].points[3] = 7;
  304. }
  305.  
  306. BOOL resize(NXSize *aSize)
  307. {
  308.     BOOL resized = NO;
  309.  
  310.     if (aSize->height > 32) {
  311.         aSize->height = 32;
  312.         resized = YES;
  313.     }
  314.  
  315.     if (aSize->width > 32) {
  316.         aSize->width = 32;
  317.         resized = YES;
  318.     }
  319.     return resized;
  320. }
  321.  
  322. - findBlockImages
  323. {
  324.     int i;
  325.     char buffer[20];
  326.     id image;
  327.     char *blockName;
  328.     BOOL isGameColor = [NXApp isGameColor];
  329.  
  330.     if (isGameColor) {
  331.         blockName = "ColorBlock";
  332.     } else {
  333.         blockName = "MonoBlock";
  334.     }
  335.     for (i=0; i<4; i++) {
  336.         sprintf(buffer, "%s%d", blockName, i+1);
  337.         image = [NXImage findImageNamed:buffer];
  338.         if (image == NULL) {
  339.             fprintf(stderr, "Couldn't find block named %s\n", buffer);
  340.             exit(0);
  341.         }
  342.         blockImage[i] = image;
  343.     }
  344.     // Assuming all the blocks are the same size.
  345.  
  346.     [blockImage[0] getSize:&blockSize];
  347.     if (resize(&blockSize)) {
  348.  
  349. #ifdef DEBUG
  350.         printf("resizing Block Image\n");
  351. #endif
  352.         [bitmap setScalable:YES];
  353.         [bitmap setSize:&blockSize];
  354.     } 
  355.  
  356.     return self;
  357. }
  358.  
  359. - init
  360. {
  361.     [super init];
  362.  
  363.     [self setShapes];
  364.  
  365.     curCol = curRow = 0;
  366.     currentPiece = PIECE_NULL;
  367.     currentShape = SHAPE_NULL;
  368.     currentRotation = shapenum = 0;
  369.  
  370.     invalidRect.origin.x = invalidRect.origin.y =
  371.       invalidRect.size.width = invalidRect.size.height = 0.0;
  372.  
  373.     // Initialized the animation Rect
  374.     {
  375.         NXSize tmp;
  376.         [self findBlockImages];
  377.  
  378.         // Limit size of block image
  379.         [blockImage[0] getSize:&tmp];
  380.         resize(&tmp);
  381.  
  382.         tmp.height *= 4;
  383.         tmp.width *= 4;
  384.  
  385.         anmShape = [[NXImage alloc] initSize:&tmp];
  386.         [anmShape lockFocus];
  387.         PSsetalpha(0.0);                  // make this block transparent
  388.         PSrectfill(0., 0., tmp.width, tmp.height);
  389.         PSsetalpha(1.0);
  390.     }
  391.     anmBackground = nil;
  392.     viewVarsInited = NO;
  393.     dropPoints = 0;
  394.     srandom(getpid());    // Initialize random number generator
  395.  
  396. #ifdef DEBUG
  397.     printf("Piece object initialized\n");
  398. #endif
  399.  
  400.     return self;
  401. }
  402.  
  403. /*
  404.  *  Draw the Piece.
  405.  *  The focus must be locked by on calling object's view before invoking this method.
  406.  */
  407. - draw:sender
  408. {
  409.     unsigned char mask;
  410.     int xc, yc;
  411.     int ycmax;
  412.     NXPoint dPt;
  413.  
  414.     ycmax = MAX_SHAPE_SIZE -
  415.       YMIN_BOUNDS(currentShape->bounds[currentRotation]);
  416.     for (yc = MAX_SHAPE_SIZE -
  417.           YMAX_BOUNDS(currentShape->bounds[currentRotation]) - 1;
  418.           yc < ycmax; yc++) {
  419.               mask = 1 << (MAX_SHAPE_SIZE - 1);
  420.               for (xc = 0; xc < MAX_SHAPE_SIZE; xc++) {
  421.                   if (currentPiece[yc] & mask) {
  422.                       // Call the sender's parent object 
  423.                       [sender point:&dPt for:curRow + MAX_SHAPE_SIZE - yc - 1 :curCol + xc];
  424.                       [bitmap composite:NX_SOVER toPoint:&dPt];
  425.                   }
  426.                   mask >>= 1;
  427.               }
  428.           }
  429.     return self;
  430. }
  431.  
  432.  
  433. /*
  434.  *  Determine what the next piece to drop will be.
  435.  *
  436.  */
  437. - newPiece
  438. {
  439.     int bitmapNum;
  440.  
  441. #ifdef DEBUG
  442.     printf("Generating a new piece\n");
  443. #endif
  444.  
  445.     shapenum = random() % NUM_SHAPES;
  446. //    shapenum = 0;
  447.     currentShape = &shapes[shapenum];
  448.     currentRotation = random() % NUM_ROTATIONS;
  449.     currentPiece = currentShape->table[currentRotation];
  450.  
  451.     bitmapNum = random() % NUM_BITMAPS;
  452.  
  453.     bitmap = blockImage[bitmapNum];
  454.  
  455.     if (bitmap == NULL) {
  456.         printf("Block %d not found\n", bitmapNum);
  457.     }
  458.     return self;
  459. }
  460.  
  461. /*
  462.  *  Needed so other objects can query to set the Window and View sizes.
  463.  */
  464. - getBlockSize:(NXSize *) size
  465. {
  466.     *size = blockSize;
  467.     return self;
  468. }
  469.  
  470. /*
  471.  *  So other objects can query Piece.m about images
  472.  */
  473. - getBlockImage:(int) blockNum
  474. {
  475.     return blockImage[blockNum];
  476. }
  477.  
  478. - (struct pieceInfo *)pieceInfo
  479. {
  480.     static struct pieceInfo info;
  481.  
  482.     info.bitmap = bitmap;
  483.     info.shape = shapenum;
  484.     info.rotation = currentRotation;
  485.     return &info;
  486. }
  487.  
  488.  
  489. - setPiece:(struct pieceInfo *)info
  490. {
  491.     bitmap = info->bitmap;
  492.     [bitmap getSize:&blockSize];
  493.     resize(&blockSize);
  494.     shapenum = info->shape;
  495.     currentShape = &shapes[shapenum];
  496.     currentRotation = info->rotation;
  497.     currentPiece = currentShape->table[currentRotation];
  498.     return self;
  499. }
  500.  
  501. /*
  502.  *  Get the next piece.
  503.  *
  504.  */
  505. - (BOOL)reset:sender piece:(struct pieceInfo *)info
  506. {
  507.     BOOL legalMove;
  508.     unsigned char shapeBounds;
  509.     int xmin, xmax;
  510.     int ymin;
  511.     NXRect bounds;
  512.  
  513. #ifdef DEBUG
  514.     printf("reseting piece\n");
  515. #endif
  516.  
  517.     // info will contain the piece from NextMatrix if Show Next is selected
  518.     // Otherwise, we'll generate a new piece. 
  519.  
  520.     if (info) {
  521.         [self setPiece:info];
  522.     } else {
  523.         [self newPiece];
  524.     }
  525.     shapeBounds = currentShape->bounds[currentRotation];
  526.     xmin = XMIN_BOUNDS(shapeBounds);
  527.     xmax = XMAX_BOUNDS(shapeBounds);
  528.     ymin = YMIN_BOUNDS(shapeBounds);
  529.     curCol = (TETRIS_COLUMNS - (xmax - xmin + 1)) / 2;
  530.     curRow = TETRIS_ROWS - ymin - 1;
  531.  
  532.     if (!viewVarsInited) {
  533.         [sender getBounds:&bounds];
  534.         [sender getIntercell:&intercell];
  535.  
  536.         // Create a new animation background
  537.         anmBackground = [[NXImage alloc] initSize:&bounds.size];
  538.         viewVarsInited = YES;
  539.     }
  540.     if ((legalMove = [self legalMove:sender :curRow :curCol rotation:currentRotation])) {
  541.         [self getInvalidRect:&invalidRect for:sender];
  542.         [sender display:&invalidRect :1];
  543.     }
  544.     dropPoints = 0;
  545.     return legalMove;
  546. }
  547.  
  548.  
  549. - (BOOL)legalMove:sender :(int)row :(int)column rotation:(int)rotation
  550. {
  551.     unsigned char mask;
  552.     int xc, yc;
  553.     int ycmax;
  554.     int ex, ey;
  555.     unsigned char *piece;
  556.  
  557.     piece = currentShape->table[rotation];
  558.     ycmax = MAX_SHAPE_SIZE - YMIN_BOUNDS(currentShape->bounds[rotation]);
  559.     for (yc = MAX_SHAPE_SIZE -
  560.           YMAX_BOUNDS(currentShape->bounds[rotation]) - 1; yc < ycmax; yc++) {
  561.               mask = 1 << (MAX_SHAPE_SIZE - 1);
  562.               for (xc = 0; xc < MAX_SHAPE_SIZE; xc++) {
  563.                   if (piece[yc] & mask) {
  564.                       ey = row + MAX_SHAPE_SIZE - yc - 1;
  565.                       ex = column + xc;
  566.                       if (ex < 0 || ex >= TETRIS_COLUMNS || ey < 0
  567.                             || [sender bitmapAt:ey :ex])
  568.                          return NO;
  569.                   }
  570.                   mask >>= 1;
  571.               }
  572.           }
  573.     return YES;
  574. }
  575.  
  576.  
  577. - left:sender
  578. {
  579.     if ([self legalMove:sender :curRow :(curCol - 1) rotation:currentRotation]) {
  580.         curCol--;
  581.         [sender display:&invalidRect :1];
  582.         [self getInvalidRect:&invalidRect for:sender];
  583.     }
  584.     return self;
  585. }
  586.  
  587. - right:sender
  588. {
  589.     if ([self legalMove:sender :curRow :(curCol + 1) rotation:currentRotation]) {
  590.         curCol++;
  591.         [sender display:&invalidRect :1];
  592.         [self getInvalidRect:&invalidRect for:sender];
  593.     }
  594.     return self;
  595. }
  596.  
  597. - getInvalidRect:(NXRect *)aRect for:sender
  598. {
  599.      unsigned char bounds;
  600.      NXRect unionRect;
  601.  
  602.      bounds = currentShape->bounds[currentRotation];
  603.      [sender getRect:&unionRect for:curRow + YMIN_BOUNDS(bounds) :curCol + XMIN_BOUNDS(bounds)];
  604.      [sender getRect: aRect for:curRow + YMAX_BOUNDS(bounds) :curCol + XMAX_BOUNDS(bounds)];
  605.      NXUnionRect(&unionRect, aRect);
  606.       
  607.      return self;
  608. }
  609.  
  610. - point:(NXPoint *)thePoint for:(int)row :(int)column 
  611. {
  612.     unsigned char bounds = currentShape->bounds[currentRotation];
  613.     int realx = column - curCol - XMIN_BOUNDS(bounds);
  614.     int realy = row - curRow - YMIN_BOUNDS(bounds);
  615.     
  616.     thePoint->x = realx * (intercell.width + blockSize.width);
  617.     thePoint->y = realy * (intercell.height + blockSize.height);
  618.     return self;
  619. }
  620.  
  621. /*
  622.  *  Called when the player his the spacebar to drop the piece. 
  623.  */
  624. - compositeShape:sender
  625. {
  626.     if (anmShape) {          // already exists
  627.         //        [self->anmShape resize:self->invalidRect.size.width :self->invalidRect.size.height];
  628.         //self->anmShape = [NXImage newSize:&self->invalidRect.size];
  629.     } else {                              // create new image
  630.         //self->anmShape = [NXImage newSize:&self->invalidRect.size];
  631.         //.width
  632.         //         :self->invalidRect.size.height type:NX_UNIQUEALPHABITMAP];
  633.         //        [self->anmShape setFlip:NO];
  634.     }
  635.     [anmShape lockFocus];
  636.     PSsetalpha(0.0);                  // Fill the window with alpha
  637.     PSrectfill(0.0, 0.0, self->invalidRect.size.width, self->invalidRect.size.height);
  638.     PSsetalpha(1.0);                  // Draw image w/o alpha
  639.     [self draw:self];
  640.     [anmShape unlockFocus];
  641.  
  642.     return self;
  643. }
  644.  
  645.  
  646. - compositeBackground: sender
  647. {
  648.     NXRect unionRect;
  649.  
  650.     [self getInvalidRect:&unionRect for:sender];
  651.     NXUnionRect(&self->invalidRect, &unionRect);
  652.     [anmBackground lockFocus];
  653.     [sender setPieceVisible:NO];
  654.     [sender drawSelf:&unionRect :1];
  655.     [sender setPieceVisible:YES];
  656.     [anmBackground unlockFocus];
  657.     return self;
  658. }
  659.  
  660. /*
  661.  *  Move the piece rapidly down the screen after the user hits the spacebar.
  662.  *
  663.  */
  664. - animateDrop:sender
  665. {
  666.     NXRect updRect;
  667.     
  668.     [self getInvalidRect:&updRect for:sender];
  669.  
  670.     [sender lockFocus];
  671.  
  672.     // Erase piece by compositing the background over it.
  673.     [anmBackground composite:NX_SOVER fromRect: &invalidRect
  674.        toPoint:&invalidRect.origin];
  675.     
  676.     while (invalidRect.origin.y - ANM_DELTA > updRect.origin.y) {
  677.         invalidRect.origin.y -= ANM_DELTA;
  678.  
  679.         // Show the piece dropping one increment
  680.         [anmShape composite:NX_SOVER toPoint:&invalidRect.origin];
  681.         [[sender window] flushWindow];
  682.  
  683.         // Erase the piece by showing the background
  684.         [anmBackground composite:NX_SOVER fromRect:&invalidRect
  685.             toPoint:&invalidRect.origin];
  686.     }
  687.     [sender unlockFocus];
  688.     
  689.     [anmShape lockFocus];
  690.     [anmShape getSize:&updRect.size];
  691.     PScompositerect(0.0, 0.0, updRect.size.width, updRect.size.height, NX_CLEAR);
  692.     [anmShape unlockFocus];
  693.     return self;
  694. }
  695.  
  696. /*
  697.  * Return the amount of points that we get for this piece.
  698.  */
  699. - (int)points
  700. {
  701.     return currentShape->points[currentRotation] + dropPoints;
  702. }
  703.  
  704. /*
  705.  * Called when the user hits the space bar.
  706.  *
  707.  */
  708. - drop:sender
  709. {
  710.     int ymin;
  711.     int yc;
  712.  
  713.     ymin = YMIN_BOUNDS(currentShape->bounds[currentRotation]);
  714.  
  715.     for (yc = curRow - 1; yc >= -1 - ymin; yc--) {
  716.         if (![self legalMove:sender :yc :curCol rotation:currentRotation])
  717.           break;
  718.     }
  719.     dropPoints += curRow - yc + 1;      // You get extra points for dropping it
  720.     curRow = yc + 1;
  721.  
  722.     [self compositeShape: sender];
  723.     [self compositeBackground: sender];
  724.     [self animateDrop: sender];
  725.  
  726.     [sender display:&invalidRect : 1];
  727.     [self getInvalidRect:&invalidRect for:sender];
  728.     return self;
  729. }
  730.  
  731. /*
  732.  * Move the piece down.
  733.  */
  734. - (BOOL)down:sender
  735. {
  736.     BOOL canGoDown;
  737.  
  738.     if ((canGoDown = [self legalMove:sender :curRow-1 :curCol rotation:currentRotation])){
  739.         curRow--;
  740.         [sender display:&invalidRect :1];
  741.         [self getInvalidRect:&invalidRect for:sender];
  742.     }
  743.     return canGoDown;
  744. }
  745.  
  746. - turn:sender
  747. {    
  748.     int newRotation = (currentRotation + 3) % NUM_ROTATIONS;
  749.     
  750.     if ([self legalMove:sender :curRow :curCol rotation:newRotation]) {
  751.         currentRotation = newRotation;
  752.         currentPiece = currentShape->table[newRotation];
  753.         [sender display:&invalidRect :1];
  754.         [self getInvalidRect:&invalidRect for:sender];
  755.     }
  756.     return self;
  757. }
  758.  
  759. /*
  760.  * Called when the piece has reached the bottom and can no longer be moved.
  761.  *
  762.  * For each block that composes the image, put the block's image id in the
  763.  * proper iconMatrix[row][column] position.  Thus to redraw the screen,
  764.  * we need only to composite the images from the iconMatrix.
  765.  */
  766. - stick:sender
  767. {
  768.     unsigned char mask;
  769.     int col, theRow;
  770.     int rowMax;
  771.  
  772.     rowMax = MAX_SHAPE_SIZE - YMIN_BOUNDS(currentShape->bounds[currentRotation]);
  773.     for (theRow = MAX_SHAPE_SIZE -
  774.           YMAX_BOUNDS(currentShape->bounds[currentRotation]) - 1;
  775.           theRow < rowMax; theRow++) {
  776.               mask = 1 << (MAX_SHAPE_SIZE - 1);
  777.               for (col = 0; col < MAX_SHAPE_SIZE; col++) {
  778.                   // If there's a block in  
  779.                   if (currentPiece[theRow] & mask)
  780.                      // Set the (row, column) of the matrix equal to Block's image.
  781.                      [sender setBitmap:bitmap at:curRow + MAX_SHAPE_SIZE - theRow - 1
  782.                                                 :curCol + col];
  783.                   mask >>= 1;
  784.               }
  785.           }
  786.     return self;
  787. }
  788.  
  789. - (int)getCurRow
  790. {
  791.     return curRow;
  792. }
  793.  
  794. - free
  795. {
  796.     if (anmShape) [anmShape free];
  797.     if (anmBackground) [anmBackground free];
  798.     return [super free];
  799. }
  800.  
  801. @@end
  802. @
  803.  
  804.  
  805. 1.7
  806. log
  807. @*** empty log message ***
  808. @
  809. text
  810. @d387 1
  811. a387 1
  812.  
  813. @
  814.  
  815.  
  816. 1.6
  817. log
  818. @*** empty log message ***
  819. @
  820. text
  821. @d269 1
  822. a269 1
  823.     const NXScreen *deepestScreen=[NXApp colorScreen];
  824. d271 1
  825. a271 1
  826.     if ( deepestScreen->depth  != NX_TwoBitGrayDepth ) {
  827. d338 1
  828. a338 1
  829.     printf("+++Piece object initialized\n");
  830. d411 8
  831. d442 4
  832. d458 2
  833. a459 4
  834.     if (info)
  835.       [self setPiece:info];
  836.     else
  837.       [self newPiece];
  838. d461 5
  839. d638 1
  840. a638 1
  841.  * Return the points that we get for this piece.
  842. @
  843.  
  844.  
  845. 1.5
  846. log
  847. @*** empty log message ***
  848. @
  849. text
  850. @d285 12
  851. a310 1
  852.     bitmapSize.width = bitmapSize.height = 0.0;
  853. d338 1
  854. a338 1
  855.     printf("Piece object initialized\n");
  856. d386 1
  857. a386 2
  858.         shapenum = random() % NUM_SHAPES;
  859. //        shapenum = 1;
  860. a398 8
  861.     [bitmap getSize:&bitmapSize];
  862.     if (resize(&bitmapSize)) {
  863. #ifdef DEBUG
  864.         printf("resizing Block Image\n");
  865. #endif
  866.         [bitmap setScalable:YES];
  867.         [bitmap setSize:&bitmapSize];
  868.     } 
  869. d402 8
  870. d425 2
  871. a426 2
  872.     [bitmap getSize:&bitmapSize];
  873.     resize(&bitmapSize);
  874. d542 2
  875. a543 2
  876.     thePoint->x = realx * (intercell.width + bitmapSize.width);
  877.     thePoint->y = realy * (intercell.height + bitmapSize.height);
  878. @
  879.  
  880.  
  881. 1.4
  882. log
  883. @*** empty log message ***
  884. @
  885. text
  886. @d5 1
  887. a6 1
  888. #import "Piece.h"
  889. d263 25
  890. a294 1
  891.     bitmap = nil;
  892. d306 1
  893. d308 4
  894. a311 3
  895.         bitmap = [NXImage findImageNamed:"Block1"];
  896.         [bitmap getSize:&tmp];
  897.         resize(&tmp);          // Limit size of block image
  898. d314 1
  899. d369 1
  900. a369 1
  901.     char *bitmapName;
  902. d382 1
  903. a382 13
  904.     switch (random() % NUM_BITMAPS) {
  905.      case 0:
  906.         bitmapName = "Block1";
  907.         break;
  908.      case 1:
  909.         bitmapName = "Block2";
  910.         break;
  911.      case 2:
  912.         bitmapName = "Block3";
  913.         break;
  914.      default:
  915.         bitmapName = "Block4";
  916.     }
  917. d384 2
  918. a385 4
  919. #ifdef DEBUG
  920.     printf("Using block image %s\n", bitmapName);
  921. #endif
  922.     bitmap = [NXImage findImageNamed:bitmapName];
  923. d387 1
  924. a387 1
  925.         printf("Block %s not found\n", bitmapName);
  926. @
  927.  
  928.  
  929. 1.3
  930. log
  931. @*** empty log message ***
  932. @
  933. text
  934. @a6 1
  935. #import "Cheater.h"
  936. d9 2
  937. a10 1
  938. static const float ANM_DELTA = 12.0;
  939. d247 16
  940. d274 1
  941. a274 1
  942.     cheating = NO;
  943. d281 7
  944. a287 1
  945.         NXSize tmp = {75., 75.}; // Must be at least 4 times block width.
  946. a296 1
  947.  
  948. d373 3
  949. d377 7
  950. a386 4
  951. - (void) setCheating:(BOOL) value
  952. {
  953.     cheating = value;
  954. }
  955. d403 1
  956. @
  957.  
  958.  
  959. 1.2
  960. log
  961. @Tetris 1.2
  962. @
  963. text
  964. @d1 1
  965. a1 1
  966.  
  967. d7 1
  968. d9 2
  969. a10 1
  970. #define ANM_DELTA    12.0
  971. d20 2
  972. a21 2
  973. #define NUM_ROTATIONS    4
  974. #define NUM_SHAPES    7
  975. d28 1
  976. a28 1
  977. static void setShapes(struct shape *shapes)
  978. d37 1
  979. a37 1
  980.     shapes[0].points[0] = 10;
  981. d250 4
  982. a253 2
  983.     setShapes(shapes);
  984.     x = y = 0;
  985. d258 1
  986. d277 5
  987. d285 4
  988. d304 3
  989. a306 2
  990.                       [sender point:&dPt for:y + MAX_SHAPE_SIZE - yc - 1 :x + xc];
  991.                       [bitmap composite:NX_COPY toPoint:&dPt];
  992. d314 1
  993. d327 3
  994. a329 1
  995.     shapenum = random() % NUM_SHAPES;
  996. d333 1
  997. a333 1
  998.     
  999. d347 4
  1000. d356 5
  1001. d391 4
  1002. d404 2
  1003. a405 2
  1004.     x = (TETRIS_COLUMNS - (xmax - xmin + 1)) / 2;
  1005.     y = TETRIS_ROWS - ymin - 1;
  1006. d412 1
  1007. a412 1
  1008.         anmBackground = [NXImage newSize:&bounds.size];
  1009. d415 1
  1010. a415 1
  1011.     if ((legalMove = [self legalMove:sender :y :x rotation:currentRotation])) {
  1012. d454 2
  1013. a455 2
  1014.     if ([self legalMove:sender :y :(x - 1) rotation:currentRotation]) {
  1015.         x--;
  1016. d464 2
  1017. a465 2
  1018.     if ([self legalMove:sender :y :(x + 1) rotation:currentRotation]) {
  1019.         x++;
  1020. d475 1
  1021. a475 1
  1022.      NXRect uRect;
  1023. d478 3
  1024. a480 3
  1025.      [sender getRect:&uRect for:y + YMIN_BOUNDS(bounds) :x + XMIN_BOUNDS(bounds)];
  1026.      [sender getRect: aRect for:y + YMAX_BOUNDS(bounds) :x + XMAX_BOUNDS(bounds)];
  1027.      NXUnionRect(&uRect, aRect);
  1028. d488 2
  1029. a489 2
  1030.     int realx = column - x - XMIN_BOUNDS(bounds);
  1031.     int realy = row - y - YMIN_BOUNDS(bounds);
  1032. d523 1
  1033. a523 1
  1034.     NXRect uRect;
  1035. d525 2
  1036. a526 2
  1037.     [self getInvalidRect:&uRect for:sender];
  1038.     NXUnionRect(&self->invalidRect, &uRect);
  1039. d529 1
  1040. a529 1
  1041.     [sender drawSelf:&uRect :1];
  1042. d535 4
  1043. a538 1
  1044.  
  1045. d546 3
  1046. a548 2
  1047.     // Erase piece
  1048.     [anmBackground composite:NX_COPY fromRect: &invalidRect
  1049. d559 2
  1050. a560 2
  1051.         [anmBackground composite:NX_COPY fromRect:&self->invalidRect
  1052.             toPoint:&self->invalidRect.origin];
  1053. d571 3
  1054. d590 2
  1055. a591 2
  1056.     for (yc = y - 1; yc >= -1 - ymin; yc--) {
  1057.         if (![self legalMove:sender :yc :x rotation:currentRotation])
  1058. d594 2
  1059. a595 2
  1060.     dropPoints += y - yc + 1;
  1061.     y = yc + 1;
  1062. d606 3
  1063. a608 1
  1064.  
  1065. d613 2
  1066. a614 2
  1067.     if ((canGoDown = [self legalMove:sender :y-1 :x rotation:currentRotation])){
  1068.         y--;
  1069. d625 1
  1070. a625 1
  1071.     if ([self legalMove:sender :y :x rotation:newRotation]) {
  1072. d635 1
  1073. a635 1
  1074.  * The piece has reached the bottom and can no longer be moved.
  1075. d637 3
  1076. d644 2
  1077. a645 2
  1078.     int xc, yc;
  1079.     int ycmax;
  1080. d647 2
  1081. a648 2
  1082.     ycmax = MAX_SHAPE_SIZE - YMIN_BOUNDS(currentShape->bounds[currentRotation]);
  1083.     for (yc = MAX_SHAPE_SIZE -
  1084. d650 1
  1085. a650 1
  1086.           yc < ycmax; yc++) {
  1087. d652 6
  1088. a657 3
  1089.               for (xc = 0; xc < MAX_SHAPE_SIZE; xc++) {
  1090.                   if (currentPiece[yc] & mask)
  1091.                      [sender setBitmap:bitmap at:y + MAX_SHAPE_SIZE - yc - 1 :x + xc];
  1092. d664 1
  1093. a664 1
  1094. - (int)y
  1095. d666 1
  1096. a666 1
  1097.     return y;
  1098. @
  1099.  
  1100.  
  1101. 1.1
  1102. log
  1103. @Initial revision
  1104. @
  1105. text
  1106. @d28 1
  1107. a28 1
  1108.     // 1st shape
  1109. d59 1
  1110. a59 1
  1111.     // 2nd shape
  1112. d90 1
  1113. a90 1
  1114.     // 3rd shape
  1115. d299 4
  1116. d307 4
  1117. d368 1
  1118. d447 2
  1119. a448 4
  1120.      [sender getRect:&uRect for:y + YMIN_BOUNDS(bounds)
  1121.         :x + XMIN_BOUNDS(bounds)];
  1122.      [sender getRect:aRect for:y + YMAX_BOUNDS(bounds)
  1123.        :x + XMAX_BOUNDS(bounds)];
  1124. d468 1
  1125. a468 1
  1126. static void compositeShape(id self, id sender)
  1127. d470 1
  1128. a470 1
  1129.     if (self->anmShape) {          // already exists
  1130. d479 1
  1131. a479 1
  1132.     [self->anmShape lockFocus];
  1133. d484 3
  1134. a486 1
  1135.     [self->anmShape unlockFocus];
  1136. d489 2
  1137. a490 1
  1138. static void compositeBackground(id self, id sender)
  1139. d493 1
  1140. a493 1
  1141.     
  1142. d496 1
  1143. a496 1
  1144.     [self->anmBackground lockFocus];
  1145. d500 2
  1146. a501 1
  1147.     [self->anmBackground unlockFocus];
  1148. d504 2
  1149. a505 1
  1150. static void animateDrop(id self, id sender)
  1151. d510 1
  1152. d513 2
  1153. a514 2
  1154.     [self->anmBackground composite:NX_COPY fromRect: &self->invalidRect
  1155.        toPoint:&self->invalidRect.origin];
  1156. d516 3
  1157. a518 2
  1158.     while (self->invalidRect.origin.y - ANM_DELTA > updRect.origin.y) {
  1159.         self->invalidRect.origin.y -= ANM_DELTA;
  1160. d520 1
  1161. a520 1
  1162.         [self->anmShape composite:NX_SOVER toPoint:&self->invalidRect.origin];
  1163. d522 1
  1164. d524 1
  1165. a524 1
  1166.         [self->anmBackground composite:NX_COPY fromRect:&self->invalidRect
  1167. d529 5
  1168. a533 5
  1169.     [self->anmShape lockFocus];
  1170.     [self->anmShape getSize:&updRect.size];
  1171.     PScompositerect(0.0, 0.0, updRect.size.width, updRect.size.height,
  1172.                          NX_CLEAR);
  1173.     [self->anmShape unlockFocus];
  1174. d549 1
  1175. a549 1
  1176.     
  1177. d551 5
  1178. a555 4
  1179.     
  1180.     for (yc = y - 1; yc >= -1 - ymin; yc--)
  1181.       if (![self legalMove:sender :yc :x rotation:currentRotation])
  1182.         break;
  1183. d559 3
  1184. a561 3
  1185.     compositeShape(self, sender);
  1186.     compositeBackground(self, sender);
  1187.     animateDrop(self, sender);
  1188. d568 1
  1189. d572 1
  1190. a572 1
  1191.     
  1192. d594 4
  1193. a602 1
  1194.     NXPoint dPt;
  1195. @
  1196.